home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume11 / sparc-mtools / part03 < prev    next >
Encoding:
Text File  |  1990-03-25  |  12.7 KB  |  515 lines

  1. Newsgroups: comp.sources.misc
  2. keywords: DOS, floppy
  3. subject: v11i083: Fast mtools,  + mkdfs for SparcStation1 or Sun-3/80 Part 3
  4. from: viktor@melon.princeton.edu (Viktor Dukhovni)
  5. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  6.  
  7. Posting-number: Volume 11, Issue 83
  8. Submitted-by: viktor@melon.princeton.edu (Viktor Dukhovni)
  9. Archive-name: sparc-mtools/part03
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 3 (of 3)."
  18. # Contents:  mwrite.c
  19. # Wrapped by viktor@cucumber on Fri Mar 16 20:50:09 1990
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'mwrite.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'mwrite.c'\"
  23. else
  24. echo shar: Extracting \"'mwrite.c'\" \(10688 characters\)
  25. sed "s/^X//" >'mwrite.c' <<'END_OF_FILE'
  26. X/*
  27. X * Write (copy) a Unix file to MSDOS
  28. X *
  29. X * Emmet P. Gray            US Army, HQ III Corps & Fort Hood
  30. X * ...!uunet!uiucuxc!fthood!egray    Attn: AFZF-DE-ENV
  31. X *                     Directorate of Engineering & Housing
  32. X *                     Environmental Management Office
  33. X *                     Fort Hood, TX 76544-5057
  34. X */
  35. X
  36. X#include <stdio.h>
  37. X#include <sys/types.h>
  38. X#include <sys/stat.h>
  39. X#include "msdos.h"
  40. X
  41. Xint fd;                /* the file descriptor for the floppy */
  42. Xint dir_start;            /* starting sector for directory */
  43. Xint dir_len;            /* length of directory (in sectors) */
  44. Xint dir_entries;        /* number of directory entries */
  45. Xint dir_chain[25];        /* chain of sectors in directory */
  46. Xint clus_size;            /* cluster size (in sectors) */
  47. Xunsigned long clus_len;        /* The cluster lenght in bytes */
  48. Xint fat_len;            /* length of FAT table (in sectors) */
  49. Xint num_clus;            /* number of available clusters */
  50. Xunsigned char *fatbuf;        /* the File Allocation Table */
  51. Xchar *mcwd;            /* the Current Working Directory */
  52. Xstatic char *inbuf;        /* The input buffer */
  53. Xstatic char *outbuf;        /* The output buffer */
  54. Xint bufsiz;            /* Buffer size */
  55. Xint maxcontig;            /* Max contiguous clusters per write call */
  56. Xlong size;            /* Size of DOS file */
  57. X
  58. Xint full = 0;
  59. Xint textmode = 0;
  60. Xint nowarn = 0;
  61. Xint need_nl = 0;
  62. X
  63. Xextern union bootblock bb;
  64. Xvoid exit(), zapit(), writefat(), writedir(), free(), perror(), move();
  65. X
  66. Xmain(argc, argv)
  67. Xint argc;
  68. Xchar *argv[];
  69. X{
  70. X    extern int optind;
  71. X    extern char *optarg;
  72. X    int i, entry, ismatch, nogo, slot, start, dot, single;
  73. X    int root, c, oops, verbose, first, mod_time;
  74. X    char *filename, *newfile, tname[9], text[4], *fixname(), *getname();
  75. X    char *unixname(), ans[10], *strncpy(), *pathname, *getpath(), *fixed;
  76. X    char tmp[MAX_PATH], *target, *strcat(), *strcpy();
  77. X    struct directory *dir, *search(), *writeit();
  78. X
  79. X    if (init(2)) {
  80. X        fprintf(stderr, "mwrite: Cannot initialize diskette\n");
  81. X        exit(1);
  82. X    }
  83. X                    /* get command line options */
  84. X    oops = 0;
  85. X    verbose = 0;
  86. X    mod_time = 0;
  87. X    while ((c = getopt(argc, argv, "tnvm")) != EOF) {
  88. X        switch(c) {
  89. X            case 't':
  90. X                textmode = 1;
  91. X                break;
  92. X            case 'n':
  93. X                nowarn = 1;
  94. X                break;
  95. X            case 'v':
  96. X                verbose = 1;
  97. X                break;
  98. X            case 'm':
  99. X                mod_time = 1;
  100. X                break;
  101. X            default:
  102. X                oops = 1;
  103. X                break;
  104. X        }
  105. X    }
  106. X
  107. X    if (oops || (argc - optind) < 2) {
  108. X        fprintf(stderr, "Usage: mwrite [-tnv] unixfile msdosfile\n");
  109. X        fprintf(stderr, "    or mwrite [-tnv] unixfile [unixfiles...] msdosdirectory\n");
  110. X        exit(1);
  111. X    }
  112. X    root = 0;
  113. X    if (!strcmp(argv[argc-1], "/") || !strcmp(argv[argc-1], "\\"))
  114. X        root = 1;
  115. X
  116. X    filename = getname(argv[argc-1]);
  117. X    pathname = getpath(argv[argc-1]);
  118. X                    /* test if path is ok first */
  119. X    if (subdir(pathname))
  120. X        exit(1);
  121. X                    /* test if last argv is a dir */
  122. X    if (isdir(filename) || root) {
  123. X        if (!strlen(pathname)) {
  124. X                    /* don't alter the presence or */
  125. X                    /* absence of a leading separator */
  126. X            strcpy(tmp, filename);
  127. X        }
  128. X        else {
  129. X            strcpy(tmp, pathname);
  130. X            strcat(tmp, "/");
  131. X            strcat(tmp, filename);
  132. X        }
  133. X                    /* subdir is not recursive */
  134. X        subdir(tmp);
  135. X        single = 0;
  136. X    }
  137. X    else {
  138. X        single = 1;
  139. X                    /* too many arguments */
  140. X        if ((argc - optind) != 2) {
  141. X            fprintf(stderr, "mwrite: too many arguments or destination directory omitted\n");
  142. X            exit(1);
  143. X        }
  144. X    }
  145. X
  146. X
  147. X    clus_len = clus_size * MSECSIZ;
  148. X    /* Round cylinder up to nearest cluster multiple */
  149. X    bufsiz = NTRACK(bb.sb) * NSECT(bb.sb);
  150. X    maxcontig = (bufsiz += clus_size - (--bufsiz) % clus_size) / clus_size;
  151. X    bufsiz *= MSECSIZ;
  152. X
  153. X    if( (outbuf = (char *)malloc(bufsiz)) == NULL ||
  154. X        ( inbuf = (char *)malloc(bufsiz)) == NULL) {
  155. X        fprintf(stderr,
  156. X            "mwrite: Cannot allocate I/O buffers\n");
  157. X        perror("malloc") ;
  158. X        exit(1);
  159. X    }
  160. X
  161. X    for (i=optind; i<argc-1; i++) {
  162. X        if (single)
  163. X            fixed = fixname(argv[argc-1], verbose);
  164. X        else
  165. X            fixed = fixname(argv[i], verbose);
  166. X
  167. X        strncpy(tname, fixed, 8);
  168. X        strncpy(text, fixed+8, 3);
  169. X        tname[8] = '\0';
  170. X        text[3] = '\0';
  171. X
  172. X        target = unixname(tname, text);
  173. X                    /* see if exists and get slot */
  174. X        ismatch = 0;
  175. X        slot = -1;
  176. X        dot = 0;
  177. X        nogo = 0;
  178. X        first = 1;
  179. X        for (entry=0; entry<dir_entries; entry++) {
  180. X            dir = search(entry);
  181. X                    /* save the '.' entry info */
  182. X            if (first) {
  183. X                first = 0;
  184. X                if ((dir->attr & 0x10) && dir->name[0] == '.') {
  185. X                    dot = dir->start[1]*0x100 + dir->start[0];
  186. X                    continue;
  187. X                }
  188. X            }
  189. X                    /* is empty */
  190. X            if (dir->name[0] == 0x0) {
  191. X                if (slot < 0)
  192. X                    slot = entry;
  193. X                break;
  194. X            }
  195. X                    /* is erased */
  196. X            if (dir->name[0] == 0xe5) {
  197. X                if (slot < 0)
  198. X                    slot = entry;
  199. X                continue;
  200. X            }
  201. X                    /* is dir or volume lable */
  202. X            if ((dir->attr & 0x10) || (dir->attr & 0x08))
  203. X                continue;
  204. X
  205. X            strncpy(tname, (char *) dir->name, 8);
  206. X            strncpy(text, (char *) dir->ext, 3);
  207. X            tname[8] = '\0';
  208. X            text[3] = '\0';
  209. X
  210. X            newfile = unixname(tname, text);
  211. X                    /* if file exists, delete it first */
  212. X            if (!strcmp(target, newfile)) {
  213. X                ismatch = 1;
  214. X                start = dir->start[1]*0x100 + dir->start[0];
  215. X                if (nowarn) {
  216. X                    zapit(start);
  217. X                    dir->name[0] = 0xe5;
  218. X                    writedir(entry, dir);
  219. X                    if (slot < 0)
  220. X                        slot = entry;
  221. X                } else {
  222. X                    while (1) {
  223. X                        printf("File \"%s\" exists, overwrite (y/n) ? ", target);
  224. X                        gets(ans);
  225. X                        if (ans[0] == 'n' || ans[0] == 'N') {
  226. X                            nogo = 1;
  227. X                            break;
  228. X                        }
  229. X                        if (ans[0] == 'y' || ans[0] == 'Y') {
  230. X                            zapit(start);
  231. X                            dir->name[0] = 0xe5;
  232. X                            writedir(entry, dir);
  233. X                            if (slot < 0)
  234. X                                slot = entry;
  235. X                            break;
  236. X                        }
  237. X                    }
  238. X                }
  239. X            }
  240. X            free(newfile);
  241. X            if (ismatch)
  242. X                break;
  243. X        }
  244. X        if (nogo) {        /* chickened out... */
  245. X            free(fixed);
  246. X            free(target);
  247. X            continue;
  248. X        }
  249. X                    /* no '.' entry means root directory */
  250. X        if (dot == 0 && slot < 0) {
  251. X            fprintf(stderr, "mwrite: No directory slots\n");
  252. X            exit(1);
  253. X        }
  254. X                    /* make the directory grow */
  255. X        if (dot && slot < 0) {
  256. X            if (grow(dot)) {
  257. X                fprintf(stderr, "mwrite: Disk full\n");
  258. X                exit(1);
  259. X            }
  260. X                    /* first entry in 'new' directory */
  261. X            slot = entry;
  262. X        }
  263. X        if (!single)
  264. X            printf("Copying %s\n", target);
  265. X                    /* write the file */
  266. X        if (dir = writeit(fixed, argv[i], verbose, mod_time))
  267. X            writedir(slot, dir);
  268. X
  269. X        free(fixed);
  270. X        free(target);
  271. X
  272. X        if (full) {
  273. X            fprintf(stderr, "mwrite: Disk Full\n");
  274. X            break;
  275. X        }
  276. X        if (single)
  277. X            break;
  278. X    }
  279. X                    /* write FAT sectors */
  280. X    writefat();
  281. X    close(fd);
  282. X    exit(0);
  283. X}
  284. X
  285. X/*
  286. X * Open the named file for write, create the cluster chain, return the
  287. X * directory structure or NULL on error.
  288. X */
  289. X
  290. Xstruct directory *
  291. Xwriteit(fixed, path, verbose, mod_time)
  292. Xchar *fixed, *path;
  293. Xint verbose, mod_time;
  294. X{
  295. X    FILE *fp;
  296. X    int fat, firstfat, oldfat, curfat, chain;
  297. X    long time(), now;
  298. X    struct directory *dir, *mk_entry();
  299. X    struct stat stbuf;
  300. X
  301. X    if (stat(path, &stbuf) < 0) {
  302. X        fprintf(stderr, "mwrite: Can't stat \"%s\"\n", path);
  303. X        return(NULL);
  304. X    }
  305. X
  306. X    if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
  307. X        if (verbose)
  308. X            fprintf(stderr, "mwrite: \"%s\" is a directory\n", path);
  309. X        return(NULL);
  310. X    }
  311. X
  312. X    if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
  313. X        fprintf(stderr, "mwrite: \"%s\" is not a regular file\n", path);
  314. X        return(NULL);
  315. X    }
  316. X                    /* preserve mod time? */
  317. X    if (mod_time)
  318. X        now = stbuf.st_mtime;
  319. X    else
  320. X        time(&now);
  321. X
  322. X    if (!(fp = fopen(path, "r"))) {
  323. X        fprintf(stderr, "mwrite: Can't open \"%s\" for read\n", path);
  324. X        return(NULL);
  325. X    }
  326. X#ifdef HAVE_SETBUFFER
  327. X    setbuffer(fp,inbuf,bufsiz) ;
  328. X#endif
  329. X
  330. X    fat = oldfat = firstfat = nextfat(size=0); 
  331. X    for(;;) {
  332. X        if (fat == -1) {
  333. X            full = 1;
  334. X            if(size) 
  335. X                zapit(firstfat) ;
  336. X            return(NULL) ;
  337. X        }
  338. X
  339. X        /*
  340. X         * grab a bunch of contiguous FAT slots
  341. X         * curfat -> 1 + last grabbed slot.
  342. X         * FIX ME!
  343. X         * someone should try to read and cache a cylinder on
  344. X         * first write access, do write to memory until a new
  345. X         * cylinder is requested.
  346. X         * The overhead is higher,  but should be more robust under
  347. X         * fragmentation.
  348. X         * In mread this may even be a win!  (Also see comments
  349. X         * in putclusters() )
  350. X         */
  351. X        for(curfat=fat; 
  352. X            ++curfat < fat + maxcontig  &&
  353. X            nextfat(curfat-1) == curfat;) ;
  354. X            
  355. X        if((oldfat=putclusters(oldfat,fat, curfat, fp)) == 0)
  356. X            break ;
  357. X
  358. X        fat = nextfat(oldfat);
  359. X    }
  360. X    fclose(fp);
  361. X    dir = mk_entry(fixed, 0x20, firstfat, size, now);
  362. X    return(dir);
  363. X}
  364. X
  365. X/*
  366. X * Write to the cluster chain from the named Unix file descriptor.
  367. X * N.B. all the clusters in the chain are contiguous.
  368. X */
  369. X
  370. X
  371. Xstatic int writepos = -1;
  372. X
  373. Xint
  374. Xputclusters(chain,start,end,fp)
  375. XFILE *fp;
  376. X{
  377. X    static int blk;
  378. X    int c, nclust, current, eof=0;
  379. X    int buflen = ( end - start ) * MSECSIZ ;
  380. X    register char *tbuf=outbuf;
  381. X
  382. X    blk = (start - 2)*clus_size + dir_start + dir_len;
  383. X
  384. X    if (textmode) { /* '\n' to '\r\n' translation */
  385. X        current = 0;
  386. X        if (need_nl) {
  387. X            tbuf[current++] = '\n';
  388. X            need_nl = 0;
  389. X        }
  390. X        while (current < buflen) {
  391. X            if ((c = fgetc(fp)) == EOF) {
  392. X                    /* put a file EOF marker */
  393. X                tbuf[current++] = 0x1a;
  394. X                ++eof;
  395. X                break;
  396. X            }
  397. X            if (c == '\n') {
  398. X                tbuf[current++] = '\r';
  399. X                /* if at the end of the buffer */
  400. X                if (current == buflen) {
  401. X                    need_nl++;
  402. X                    break;
  403. X                }
  404. X            }
  405. X            tbuf[current++] = c;
  406. X        }
  407. X    }
  408. X    else {
  409. X        /*
  410. X         * FIX ME!
  411. X         * The kernel guarantees to satisfy REGULAR file
  412. X         * read requests unless EOF,
  413. X         * This code will break on pipes,  sockets,  etc.
  414. X         * To fix one should do something akin to the
  415. X         * "atomic" I/O of Berkeley multiprocess dump,  which loops
  416. X         * on read/write requests until EOF or enough data has been
  417. X         * gathered.  If you want to do this please change
  418. X         * all instances of  read/write with Read/Write and
  419. X         * add an offset parameter to allow arbitrary sorting/queuing
  420. X         * etc,  behind the back of the DOS code.  This will
  421. X         * make the overall code much cleaner,  and we 
  422. X         * can put Read/Write in a sysdep.c where they belong.
  423. X         * Also one may want to memory map the input file.  Avoiding
  424. X         * redundant copying to user space,  this is for perfectionists
  425. X         * as the floppy is much slower than UNIX disks,  so gains
  426. X         * here are small.
  427. X         */
  428. X        if ( (current = fread(outbuf, 1, buflen, fp)) < 0) {
  429. X            perror("putcluster: fread");
  430. X            exit(1);
  431. X        }
  432. X        if ( current != buflen ) 
  433. X            ++eof;
  434. X    }
  435. X
  436. X    size += current;
  437. X
  438. X    if (current == 0) {
  439. X        putfat(chain,0xfff) ;
  440. X        return(0) ;
  441. X    }
  442. X
  443. X    putfat(chain,start) ;
  444. X
  445. X    /*
  446. X     * chain the clusters, we are about to overwrite
  447. X     * making sure to terminate the chain.
  448. X     */
  449. X    for(end=start; current > clus_len ; ++end) {
  450. X        putfat(end,end+1);
  451. X        current -= clus_len ;
  452. X    }
  453. X    putfat(end, 0xfff) ;
  454. X
  455. X    if ( blk != writepos )
  456. X        move(blk);
  457. X
  458. X    nclust=(end-start)+1;
  459. X    writepos = eof ? -1 : blk + nclust*clus_size;
  460. X    buflen = nclust * clus_size * MSECSIZ;
  461. X
  462. X    if (write(fd, outbuf, buflen) != buflen) {
  463. X        perror("putclusters: write");
  464. X        exit(1);
  465. X    }
  466. X
  467. X    return(eof ? 0: end) ;
  468. X}
  469. X
  470. X/*
  471. X * Returns next free cluster or -1 if none are available.
  472. X */
  473. X
  474. Xint
  475. Xnextfat(last)
  476. Xint last;
  477. X{
  478. X    register int i;
  479. X
  480. X    for (i=last+1; i<num_clus+2; i++) {
  481. X        if (!getfat(i))
  482. X            return(i);
  483. X    }
  484. X    return(-1);
  485. X
  486. X}
  487. END_OF_FILE
  488. if test 10688 -ne `wc -c <'mwrite.c'`; then
  489.     echo shar: \"'mwrite.c'\" unpacked with wrong size!
  490. fi
  491. # end of 'mwrite.c'
  492. fi
  493. echo shar: End of archive 3 \(of 3\).
  494. cp /dev/null ark3isdone
  495. MISSING=""
  496. for I in 1 2 3 ; do
  497.     if test ! -f ark${I}isdone ; then
  498.     MISSING="${MISSING} ${I}"
  499.     fi
  500. done
  501. if test "${MISSING}" = "" ; then
  502.     echo You have unpacked all 3 archives.
  503.     rm -f ark[1-9]isdone
  504. else
  505.     echo You still need to unpack the following archives:
  506.     echo "        " ${MISSING}
  507. fi
  508. ##  End of shell archive.
  509. exit 0
  510.     Viktor Dukhovni <viktor@math.princeton.edu>    : ARPA
  511.         <...!uunet!princeton!math!viktor>    : UUCP
  512.     Fine Hall, Washington Rd., Princeton, NJ 08544  : US-Post
  513.         +1-(609)-258-5792             : VOICE
  514.  
  515.